package com.pet.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pet.common.model.PageModel;
import com.pet.system.constant.RoleStatus;
import com.pet.system.domain.entity.SysRole;
import com.pet.system.domain.entity.SysRoleResource;
import com.pet.system.domain.entity.SysRoleUser;
import com.pet.system.domain.vo.SysRoleVO;
import com.pet.system.mapper.SysRoleMapper;
import com.pet.system.mapper.SysRoleResourceMapper;
import com.pet.system.mapper.SysRoleUserMapper;
import com.pet.system.service.ISysRoleService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/** @author Centaurea */
@Service
@AllArgsConstructor
public class SysRoleServiceImpl implements ISysRoleService {
  private final SysRoleMapper roleMapper;
  private final SysRoleResourceMapper roleResourceMapper;
  private final SysRoleUserMapper roleUserMapper;

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void save(SysRoleVO roleDto) {
    // 校验处理,修改
    if (roleDto.getId() != null) {
      SysRole role = roleMapper.selectById(roleDto.getId());
      if (role == null) {
        throw new IllegalArgumentException(
            String.format("the roleId (%d) is already exist !", roleDto.getId()));
      }
      roleMapper.updateById(roleDto);
    } else {
      roleMapper.insert(roleDto);
    }
    // 处理角色和资源关联关系
    saveRoleResource(roleDto.getId(), roleDto.getResourceIds());
  }

  private void saveRoleResource(Integer roleId, List<Integer> resourceIds) {
    if (roleId == null) {
      return;
    }
    // 先删，再增( 先取当前的， 如果一致则不执行，否则按先删后增)
    QueryWrapper<SysRoleResource> queryWrapper1 = new QueryWrapper<>();
    queryWrapper1.eq(SysRoleResource.COL_ROLE_ID, roleId);
    List<SysRoleResource> sysUserResources = roleResourceMapper.selectList(queryWrapper1);
    List<Integer> curResIds =
        sysUserResources.stream()
            .map(sysRoleResource -> Integer.valueOf(sysRoleResource.getResourceId()))
            .collect(Collectors.toList());
    if (resourceIds != null) {
      Comparator<Integer> sort = Integer::compareTo;
      curResIds.sort(sort);
      resourceIds.sort(sort);
      if (curResIds.equals(resourceIds)) {
        return;
      }
    }
    // list 标准排序后，比较即可
    if (roleResourceMapper.delete(queryWrapper1) != 1) {
      throw new RuntimeException(String.format("delete roleId(= %d) is fail !", roleId));
    }
    if (resourceIds != null && !CollectionUtils.isEmpty(resourceIds)) {
      List<SysRoleResource> list = new ArrayList<>();
      for (Integer resourceId : resourceIds) {
        SysRoleResource sysRoleResource = new SysRoleResource();
        sysRoleResource.setRoleId(Math.toIntExact(roleId));
        sysRoleResource.setResourceId(Math.toIntExact(resourceId));
        list.add(sysRoleResource);
      }
      int i = roleResourceMapper.batchInsert(list);
      if (i != resourceIds.size()) {
        throw new RuntimeException(
            String.format(
                "add 「roleId(%d) and resources(%s)」 is fail", roleId, resourceIds.toString()));
      }
    }
  }

  @Override
  public boolean updateStatus(Integer id, Integer status) {
    if (RoleStatus.DISABLED.getStatus() != status) {
      status = RoleStatus.NORMAL.getStatus();
    }
    SysRole sysRole = roleMapper.selectById(id);
    sysRole.setStatus(status);
    int i = roleMapper.updateById(sysRole);
    return i == 1;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void delete(List<Integer> roleIds) {
    for (Integer roleId : roleIds) {
      if (roleId == null) {
        continue;
      }
      // 删除 角色用户关系、角色资源关系、自身
      QueryWrapper<SysRoleUser> queryWrapper1 = new QueryWrapper<>();
      queryWrapper1.eq(SysRoleUser.COL_ROLE_ID, roleId);
      roleUserMapper.delete(queryWrapper1);

      QueryWrapper<SysRoleResource> queryWrapper2 = new QueryWrapper<>();
      queryWrapper2.eq(SysRoleResource.COL_ROLE_ID, roleId);
      roleResourceMapper.delete(queryWrapper2);

      roleMapper.deleteById(roleId);
    }
  }

  @Override
  public List<SysRole> queryAll(Map<String, Object> params) {
    QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
    for (String key : params.keySet()) {
      queryWrapper.like(key, params.get(key));
    }
    return roleMapper.selectList(queryWrapper);
  }

  @Override
  public List<SysRole> queryAllByPage(PageModel<SysRole> pageModel, Map<String, Object> params) {
    QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();
    if (params.get(SysRole.COL_STATUS) != null) {
      queryWrapper.eq(SysRole.COL_STATUS, params.get(SysRole.COL_STATUS));
    }
    if (params.get("searchWord") != null) {
      queryWrapper
          .like(SysRole.COL_NAME, params.get("searchWord"))
          .or()
          .like(SysRole.COL_DESCRIPTION, params.get("searchWord"));
    }
    return roleMapper.selectList(queryWrapper);
  }
}
